package com.cc.wechat.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cc.wechat.common.ResultCode;
import com.cc.wechat.common.constants.UserConstants;
import com.cc.wechat.dto.request.LoginRequest;
import com.cc.wechat.dto.request.RegisterRequest;
import com.cc.wechat.dto.response.JwtAuthResponse;
import com.cc.wechat.dto.response.RegisterResponse;
import com.cc.wechat.dto.response.UserSearchResponse;
import com.cc.wechat.entity.Contact;
import com.cc.wechat.entity.User;
import com.cc.wechat.exception.BusinessException;
import com.cc.wechat.mapper.ContactMapper;
import com.cc.wechat.mapper.UserMapper;
import com.cc.wechat.security.JwtTokenProvider;
import com.cc.wechat.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;

/**
 * 用户服务实现类
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final ContactMapper contactMapper;
    private final PasswordEncoder passwordEncoder;
    private final AuthenticationManager authenticationManager;
    private final JwtTokenProvider tokenProvider;

    /**
     * 用户登录
     * 支持使用用户名或邮箱登录
     * 登录成功后会更新最后登录时间并生成JWT令牌
     *
     * @param loginRequest 登录请求参数（账号和密码）
     * @return JWT认证响应，包含令牌和用户信息
     */
    @Override
    @Transactional
    public JwtAuthResponse login(LoginRequest loginRequest) {
        // 先尝试通过用户名查找用户
        User user = lambdaQuery()
                .eq(User::getUsername, loginRequest.getAccount())
                .or()
                .eq(User::getEmail, loginRequest.getAccount())
                .one();

        if (user == null) {
            throw new BusinessException(ResultCode.USER_NOT_FOUND, UserConstants.Message.USER_NOT_FOUND);
        }

        try {
            // 验证用户凭据
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            user.getUsername(),
                            loginRequest.getPassword()
                    )
            );

            // 设置认证信息到上下文
            SecurityContextHolder.getContext().setAuthentication(authentication);
            String jwt = tokenProvider.generateToken(authentication);

            // 更新最后登录时间
            updateLastLoginTime(user.getUsername());

            // 构建响应
            return JwtAuthResponse.builder()
                    .token(jwt)
                    .userId(user.getId())
                    .username(user.getUsername())
                    .nickname(user.getNickname())
                    .avatar(user.getAvatar())
                    .email(user.getEmail())
                    .build();
        } catch (Exception e) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED, UserConstants.Message.INVALID_CREDENTIALS);
        }
    }

    /**
     * 用户注册
     * 注册前会检查用户名和邮箱是否已被使用
     *
     * @param registerRequest 注册请求参数（用户名、密码、邮箱等）
     * @return 注册响应，包含用户ID和基本信息
     */
    @Override
    @Transactional
    public RegisterResponse register(RegisterRequest registerRequest) {
        // 检查用户名是否已存在
        if (existsByUsername(registerRequest.getUsername())) {
            throw new BusinessException(ResultCode.USERNAME_ALREADY_EXISTS, UserConstants.Message.USERNAME_ALREADY_EXISTS);
        }

        // 检查邮箱是否已被注册
        if (existsByEmail(registerRequest.getEmail())) {
            throw new BusinessException(ResultCode.EMAIL_ALREADY_EXISTS, UserConstants.Message.EMAIL_ALREADY_EXISTS);
        }

        // 创建新用户
        User user = new User();
        user.setUsername(registerRequest.getUsername());
        user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
        user.setEmail(registerRequest.getEmail());
        user.setNickname(registerRequest.getNickname());
        user.setLastLoginTime(LocalDateTime.now());
        user.setEnabled(true);

        save(user);

        return RegisterResponse.builder()
                .userId(user.getId())
                .username(user.getUsername())
                .email(user.getEmail())
                .message(UserConstants.Message.REGISTER_SUCCESS)
                .build();
    }

    /**
     * 获取当前登录用户
     * 从Spring Security上下文中获取当前认证用户的信息
     *
     * @return 当前登录用户实体
     */
    @Override
    public User getCurrentUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User user = lambdaQuery()
                .eq(User::getUsername, authentication.getName())
                .one();
                
        if (user == null) {
            throw new BusinessException(ResultCode.USER_NOT_FOUND, UserConstants.Message.USER_NOT_FOUND);
        }
        
        return user;
    }

    /**
     * 更新用户最后登录时间
     * 在用户每次成功登录后调用
     *
     * @param username 用户名
     */
    @Override
    @Transactional
    public void updateLastLoginTime(String username) {
        boolean updated = lambdaUpdate()
                .eq(User::getUsername, username)
                .set(User::getLastLoginTime, LocalDateTime.now())
                .update();
                
        if (!updated) {
            throw new BusinessException(ResultCode.USER_NOT_FOUND, UserConstants.Message.USER_NOT_FOUND);
        }
    }

    /**
     * 检查用户名是否已存在
     * 用于注册时的用户名查重
     *
     * @param username 用户名
     * @return 如果用户名已存在返回true，否则返回false
     */
    @Override
    public boolean existsByUsername(String username) {
        return lambdaQuery()
                .eq(User::getUsername, username)
                .exists();
    }

    /**
     * 检查邮箱是否已被注册
     * 用于注册时的邮箱查重
     *
     * @param email 电子邮箱
     * @return 如果邮箱已被注册返回true，否则返回false
     */
    @Override
    public boolean existsByEmail(String email) {
        return lambdaQuery()
                .eq(User::getEmail, email)
                .exists();
    }

    /**
     * 通过邮箱搜索用户
     * 用于添加好友时的用户搜索
     * @param email 用户邮箱
     * @return 匹配的用户信息，如果未找到返回null
     */
    @Override
    public UserSearchResponse searchUserByEmail(String email) {
        // 1. 参数校验
        if (!StringUtils.hasText(email)) {
            throw new BusinessException(ResultCode.VALIDATE_FAILED, UserConstants.Message.EMAIL_EMPTY);
        }

        // 2. 获取当前用户ID
        User currentUser = getCurrentUser();
        Long currentUserId = currentUser.getId();

        // 3. 查询用户
        User user = lambdaQuery()
                .eq(User::getEmail, email)
                .one();
        if (user == null) {
            // 抛异常：用户不存在
            throw new BusinessException(ResultCode.USER_NOT_FOUND, UserConstants.Message.USER_NOT_FOUND);
        }

        // 4. 查询好友关系
        Contact contact = null;
        if (!currentUserId.equals(user.getId())) {
            // 表示根据邮箱搜索的用户不是当前用户
            contact = contactMapper.selectOne(
                new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Contact>()
                    .eq(Contact::getUserId, currentUserId)
                    .eq(Contact::getFriendId, user.getId())
            );
        }

        // 5. 构建响应
        return UserSearchResponse.builder()
                .id(user.getId())
                .username(user.getUsername())
                .nickname(user.getNickname())
                .avatar(user.getAvatar())
                .email(user.getEmail())
                .isFriend(contact != null)
                .friendStatus(contact != null ? contact.getStatus() : null)
                .build();
    }
} 